// Serial.cpp
//#include "stdafx.h"
#include "Serial.h"
#include <stdio.h>

//------------------------------------------------------------------------------
CSerial::CSerial()
{

	memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
 	memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
	m_hIDComDev = NULL;
	m_bOpened = FALSE;

}
//------------------------------------------------------------------------------
CSerial::~CSerial()
{

	Close();

}
//------------------------------------------------------------------------------
bool CSerial::Open( int nPort, int nBaud )
{

    if( m_bOpened ) return( TRUE );

    char szPort[25], szPortNumber[25];
    char szComParams[50];
    DCB dcb;

    wsprintf( szPortNumber, "COM%d", nPort );

    strcpy(szPort, "//./");  // not needed in XP
    strcat(szPort, szPortNumber);


    m_hIDComDev = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
    if( m_hIDComDev == NULL ) return( FALSE );

    memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
    memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );

    COMMTIMEOUTS CommTimeOuts;
    CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
    CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
    CommTimeOuts.ReadTotalTimeoutConstant = 0;
    CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
    CommTimeOuts.WriteTotalTimeoutConstant = 5000;
    SetCommTimeouts( m_hIDComDev, &CommTimeOuts );

    wsprintf( szComParams, "COM%d:%d,n,8,1", nPort, nBaud );

    m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
    m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );

    dcb.DCBlength = sizeof( DCB );
    GetCommState( m_hIDComDev, &dcb );
    dcb.BaudRate = nBaud;
    dcb.ByteSize = 8;
    unsigned char ucSet;
    ucSet = (unsigned char) ( ( FC_RTSCTS & FC_DTRDSR ) != 0 );
    ucSet = (unsigned char) ( ( FC_RTSCTS & FC_RTSCTS ) != 0 );
    ucSet = (unsigned char) ( ( FC_RTSCTS & FC_XONXOFF ) != 0 );
    if( !SetCommState( m_hIDComDev, &dcb ) ||
            !SetupComm( m_hIDComDev, 10000, 10000 ) ||
            m_OverlappedRead.hEvent == NULL ||
            m_OverlappedWrite.hEvent == NULL ){

            DWORD dwError = GetLastError();
            LPTSTR pszMessage;

            FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dwError,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &pszMessage,
        0, NULL );

            printf("%s", pszMessage);

            if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
            if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
            CloseHandle( m_hIDComDev );
            printf("a ajuns\n");
            return( FALSE );
            }

    m_bOpened = TRUE;

    return( m_bOpened );

}
//------------------------------------------------------------------------------
bool CSerial::Close( void )
{

  if( !m_bOpened || m_hIDComDev == NULL ) return( TRUE );

  if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
  if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
  CloseHandle( m_hIDComDev );
  m_bOpened = FALSE;
  m_hIDComDev = NULL;

  return( TRUE );

}
//------------------------------------------------------------------------------
bool CSerial::WriteCommByte( unsigned char ucByte )
{
  BOOL bWriteStat;
  DWORD dwBytesWritten;

  bWriteStat = WriteFile( m_hIDComDev, (LPSTR) &ucByte, 1, &dwBytesWritten, &m_OverlappedWrite );



  if( !bWriteStat && ( GetLastError() == ERROR_IO_PENDING ) ){
          if( WaitForSingleObject( m_OverlappedWrite.hEvent, 1000 ) ) dwBytesWritten = 0;
          else{
                  GetOverlappedResult( m_hIDComDev, &m_OverlappedWrite, &dwBytesWritten, FALSE );
                  m_OverlappedWrite.Offset += dwBytesWritten;
                  }
          }

  return( TRUE );

}
//------------------------------------------------------------------------------
int CSerial::SendData( const char *buffer, int size )
{
  if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );

  DWORD dwBytesWritten = 0;
  int i;
  for( i=0; i<size; i++ ){
          WriteCommByte( buffer[i] );
          dwBytesWritten++;
          }

  return( (int) dwBytesWritten );

}
//------------------------------------------------------------------------------
int CSerial::ReadDataWaiting( void )
{

  if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );

  DWORD dwErrorFlags;
  COMSTAT ComStat;

  ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );

  return( (int) ComStat.cbInQue );

}
//------------------------------------------------------------------------------
int CSerial::ReadData( void *buffer, int limit )
{

  if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );

  BOOL bReadStatus;
  DWORD dwBytesRead, dwErrorFlags;
  COMSTAT ComStat;

  ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
  if( !ComStat.cbInQue ) return( 0 );

  dwBytesRead = (DWORD) ComStat.cbInQue;
  if( limit < (int) dwBytesRead ) dwBytesRead = (DWORD) limit;

  bReadStatus = ReadFile( m_hIDComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
  if( !bReadStatus ){
          if( GetLastError() == ERROR_IO_PENDING ){
                  WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
                  return( (int) dwBytesRead );
                  }
          return( 0 );
          }

  return( (int) dwBytesRead );

}
//------------------------------------------------------------------------------
